import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:logger/logger.dart' show Level, Logger;
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter_sound_platform_interface/flutter_sound_platform_interface.dart';
import 'package:flutter_sound_platform_interface/flutter_sound_recorder_platform_interface.dart';

import 'ly_voice_player.dart';

typedef TDRecordCallback = void Function(
    bool isFinish, String path, double second);

//音频录制单例
class LYVoiceRecorder {
  factory LYVoiceRecorder() => _instance;
  static final LYVoiceRecorder _instance = LYVoiceRecorder._internal();
  LYVoiceRecorder._internal();

  FlutterSoundRecorder recorderModule =
      FlutterSoundRecorder(logLevel: Level.error);

  TDRecordCallback? recordCallback;

  int maxLength = 60;
  double recordSecond = 0;
  String recordPath = "";

  /// 开始录音
  Future<bool> startRecord(TDRecordCallback callBack) async {
    var isSetUp = await setupRecordVoice();
    if (isSetUp) {
      recordCallback = callBack;
      _realStartPlay(callBack);
      return true;
    }
    return false;
  }

  bool get isRecording =>
      recorderModule.recorderState == RecorderState.isRecording;

  stopIfRecording() {
    if (isRecording) {
      stopRecorder();
    }
  }

  /// 结束录音
  stopRecorder() async {
    try {
      await recorderModule.stopRecorder();
      recordCallback?.call(true, recordPath, recordSecond);
      recordPath = '';
      recordSecond = 0;
      recordCallback = null;
    } catch (err) {}
  }

  setupRecordVoice() async {
    //关闭播放
    LYVoicePlayer().pausePlayer(true);
    var status = await getPermissionStatus();
    if (status) {
      if (recorderModule.isStopped) {
        await initVoice();
      }
      return true;
    }
    return false;
  }

  Future<void> initVoice() async {
    //开启录音
    await recorderModule.openRecorder();
    await LYVoicePlayer().setUpPlayerConfig();
    //设置订阅计时器
    await recorderModule
        .setSubscriptionDuration(const Duration(milliseconds: 1000));
  }

  Future<bool> getPermissionStatus() async {
    Permission permission = Permission.microphone;
    //granted 通过，denied 被拒绝，permanentlyDenied 拒绝且不在提示
    PermissionStatus status = await permission.status;
    if (status.isGranted) {
      return true;
    } else if (status.isDenied) {
      debugPrint('isDenied');
      await requestPermission(permission);
      return false;
    } else if (status.isPermanentlyDenied) {
      debugPrint('isPermanentlyDenied');
      openAppSettings();
    } else if (status.isRestricted) {
      debugPrint('isPermanentlyDenied');
      await requestPermission(permission);
      return false;
    } else {}
    return false;
  }

  ///申请权限
  Future<bool> requestPermission(Permission permission) async {
    PermissionStatus status = await permission.request();
    if (status.isPermanentlyDenied) {
      openAppSettings();
    }
    return status == PermissionStatus.granted;
  }

  _realStartPlay(TDRecordCallback callBack) async {
    try {
      Directory applicationDir = await getApplicationDocumentsDirectory();
      bool isDirExist =
          await Directory("${applicationDir.path}/voices").exists();
      if (!isDirExist) Directory("${applicationDir.path}/voices").create();
      final fileName = "${DateTime.now().millisecondsSinceEpoch}.mp4";
      String path = '${applicationDir.path}/voices/$fileName';
      bool isSupported = await recorderModule.isEncoderSupported(Codec.aacMP4);
      debugPrint("1------> path $isSupported == $path");
      try {
        await recorderModule.startRecorder(
            codec: Codec.aacMP4,
            toFile: path,
            bitRate: 8000,
            sampleRate: 8000,
            audioSource: AudioSource.microphone);
      } on Exception catch (exception) {
        // exception.runtimeType
        debugPrint(
            'e.toStri----> ${exception.runtimeType} ${exception.toString()}');
        stopRecorder();
        return;
      }

      recordPath = fileName;
      debugPrint('1------>   开始录音 $recordPath');

      /// 监听录音
      recorderModule.onProgress!.listen((e) {
        DateTime date = DateTime.fromMillisecondsSinceEpoch(
            e.duration.inMilliseconds,
            isUtc: true);
        debugPrint("1------>时间：${date.second}");
        // print("---->当前振幅：${e.decibels}");
        callBack.call(false, path, date.second.toDouble());
        recordSecond = date.second.toDouble();
        if (date.second >= maxLength) {
          debugPrint('1------>  到达时常停止录音');
          stopRecorder();
        }
      });
    } catch (err) {
      debugPrint(err.toString());
      stopRecorder();
    }
  }
}
